﻿using Framework.Common.Attributes;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

namespace Framework.Common.DynamicInjection
{
    /// <summary>
    /// 多实现注入
    /// </summary>
    public static class MultiImplServerExtension
    {
        /// <summary>
        /// 使用 MultiImpl 特性的所有接口
        /// </summary>
        private static readonly List<Type> _cachedMarkedInterfaces = [];
        /// <summary>
        /// 所有类（不包含抽象类）
        /// </summary>
        private static readonly List<Type> _cachedImplementations = [];

        /// <summary>
        /// 多实现自动注入
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddMultiImplServer(this IServiceCollection services)
        {
            // 首次调用时扫描并缓存
            if (_cachedMarkedInterfaces.Count == 0)
            {
                ScanAssemblies();
            }

            // 注册所有实现
            foreach (var interfaceType in _cachedMarkedInterfaces)
            {
                var implementations = _cachedImplementations
                    .Where(x => interfaceType.IsAssignableFrom(x) && !x.IsAbstract);

                foreach (var impl in implementations)
                {
                    services.AddScoped(interfaceType, impl);
                }
            }

            return services;
        }

        /// <summary>
        /// 缓存
        /// </summary>
        private static void ScanAssemblies()
        {
            //获取所有程序集
            var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(asm => !asm.IsDynamic && !asm.FullName!.StartsWith("System.")); // 排除系统和动态程序集
            //便利所有程序集信息
            foreach (var assembly in assemblies)
            {
                try
                {
                    var types = assembly.GetTypes();
                    //获取所有使用了 MultiImplAttribute 接口
                    _cachedMarkedInterfaces.AddRange(
                        types.Where(x => x.IsInterface && x.GetCustomAttribute<MultiImplAttribute>() != null)
                    );
                    //获取所有类（不包含抽象类）
                    _cachedImplementations.AddRange(
                        types.Where(x => x.IsClass && !x.IsAbstract)
                    );
                }
                catch (ReflectionTypeLoadException ex)
                {
                    Console.WriteLine($"多实现自动注入程序集获取失败：{ex.Message}，异常明细：{ex}");
                }
            }
        }
    }
}
